/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.zhiqim.kernel.annotation.AnAlias;
import org.zhiqim.kernel.annotation.AnNullable;

/**
 * 操作系统命令相关工具类
 * 
 * @version v1.0.0 @author zouzhigang 2014-2-27 新建与整理
 */
@AnAlias("Runtimes")
public class Runtimes
{
    /***************************************************************/
    //读取命令操作的结果
    /***************************************************************/
    
    /**
     * 有参数命令获取数据结果字符串，字符串以流来判断
     * 
     * @param cmdarray      命令集
     * @return              命令结果
     * @throws IOException  IO异常要求业务捕捉
     */
    public static String exec(String[] cmdarray) throws IOException
    {
        Process p =  Runtime.getRuntime().exec(cmdarray);
        byte[] bytes = Streams.getBytes(p.getInputStream());
        String encoding = Streams.getStreamEncoding(bytes, bytes.length);
        return new String(bytes, encoding);
    }
    
    /**
     * 有参数命令获取数据结果字符串
     * 
     * @param cmdarray      命令集
     * @param encoding      编码
     * @return              命令结果
     * @throws IOException  IO异常要求业务捕捉
     */
    public static String exec(String[] cmdarray, String encoding) throws IOException
    {
        return exec(cmdarray, Charset.forName(encoding));
    }
    
    /**
     * 有参数命令获取数据结果字符串
     * 
     * @param cmdarray      命令集
     * @param charset       字符集
     * @return              命令结果
     * @throws IOException  IO异常要求业务捕捉
     */
    public static String exec(String[] cmdarray, Charset charset) throws IOException
    {
        Process p =  Runtime.getRuntime().exec(cmdarray);
        return Streams.getString(p.getInputStream(), charset);
    }
    
    /**
     * 有参数命令获取数据结果行，指定需要的行数
     * 
     * @param cmd           命令行
     * @param encoding      编码
     * @param maxLineNum    行数，则读到指令行数即停止，0表示读所有
     * @return List<String> 字符串列表值
     * @throws IOException  IO异常要求业务捕捉
     */
    public static List<String> exec(String[] cmdarray, String encoding, int maxLineNum) throws IOException
    {
        return exec(cmdarray, Charset.forName(encoding), maxLineNum);
    }
    
    /**
     * 有参数命令获取数据结果行，指定需要的行数
     * 
     * @param cmd           命令行
     * @param charset       字符集
     * @param maxLineNum    行数，则读到指令行数即停止，0表示读所有
     * @return List<String> 字符串列表值
     * @throws IOException  IO异常要求业务捕捉
     */
    public static List<String> exec(String[] cmd, Charset charset, int maxLineNum) throws IOException
    {
        List<String> lines = new ArrayList<String>();
        InputStream is = null;
        BufferedReader reader = null;
        
        try
        {
            Process p =  Runtime.getRuntime().exec(cmd);
            reader = new BufferedReader(new InputStreamReader(p.getInputStream(), charset));
            
            String line = null;
            while((line = reader.readLine()) != null)
            {
                lines.add(line);
                
                if (maxLineNum > 0 && lines.size() >= maxLineNum)
                    return lines;
            }

            return lines;
        }
        finally
        {
            Closes.closeIgnoreException(reader, is);
        }
    }
    
    /***************************************************************/
    //双系统通用的功能
    /***************************************************************/
    
    /**
     * 获取第一个MAC地址，结果为null表示未找到
     * 
     * @return              MAC地址
     * @throws IOException  IO异常
     */
    @AnNullable
    public static String getFirstMacAddress() throws IOException
    {
        return Systems.isWindows()?Windows.getFirstMacAddress():Linux.getFirstMacAddress();
    }
}
